function Mvvm(options) {
    this.$options = options; //将传入的参数赋值给$options
    let data = this.$data = this._data = options.data;

    // 因为JavaScript object 是引用类型
    // 所以只需要更改一个代理data，其他的也会相应更改
    observer(data, data);  // 数据劫持

    for (let k in data) { // 为了可以便携使用（this[key]）
        Object.defineProperty(this, k, {
            enumerable: true,
            get() {
                return this._data[k]
            },
            set(newVal) {
                if (newVal === this.$data[k]) {
                    return
                }
                this.$data[k] = newVal;
            }
        });
        observer(data[k]);
    }
}

function observer(data) {
    if (typeof data === 'object') { // 如果是object，说明可以进行数据劫持
        for (let k in data) {
            let val = data[k];
            Object.defineProperty(data, k, {
                enumerable: true,  // 是否可枚举
                get() {  // get对象
                    return val
                },
                set(newVal) {  // set对象。参数是新值
                    if (newVal === val) {   // 如果新值 === 更改前的值
                        return
                    }
                    val = newVal; // 赋值
                }
            });
            observer(val);  // 继续进行深度监听
        }
    }
    return false;
}